package com.yanqu.road.server.gameplayer.module.beautyescort;

import com.yanqu.road.entity.beautyescort.*;
import com.yanqu.road.entity.beautyescort.rank.EscortWeekRewardInfo;
import com.yanqu.road.entity.beautyescort.rank.EscortWeekUserValue;
import com.yanqu.road.entity.config.beauty.BeautyInfo;
import com.yanqu.road.entity.config.goods.GoodsInfo;
import com.yanqu.road.entity.config.skill.SkillInfo;
import com.yanqu.road.entity.enums.*;
import com.yanqu.road.entity.log.LogBeautyEscortDartReward;
import com.yanqu.road.entity.log.LogBeautyEscortEventReward;
import com.yanqu.road.entity.log.LogBeautySkillExp;
import com.yanqu.road.entity.player.UserBeauty;
import com.yanqu.road.entity.player.UserPatrons;
import com.yanqu.road.entity.player.UserPatronsSkill;
import com.yanqu.road.entity.task.args.UnionRiseRankArgs;
import com.yanqu.road.entity.union.UnionInfo;
import com.yanqu.road.entity.union.cross.CrossUnionMember;
import com.yanqu.road.logic.bussiness.beautyescort.BeautyEscortBussiness;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.message.YanQuMessage;
import com.yanqu.road.pb.beautyescort.BeautyEscortProto;
import com.yanqu.road.server.GameServer;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.base.GeneralModule;
import com.yanqu.road.server.gameplayer.module.patrons.PatronsModule;
import com.yanqu.road.server.gameplayer.module.player.BagModule;
import com.yanqu.road.server.gameplayer.module.player.BeautyModule;
import com.yanqu.road.server.gameplayer.module.player.CurrencyModule;
import com.yanqu.road.server.gameplayer.module.player.PreReduceModule;
import com.yanqu.road.server.manger.ConfigMgr;
import com.yanqu.road.server.manger.activity.curio.CurioMgr;
import com.yanqu.road.server.manger.beautyescort.BeautyEscortMgr;
import com.yanqu.road.server.manger.config.*;
import com.yanqu.road.server.manger.log.AutoLogMgr;
import com.yanqu.road.server.manger.log.LogMgr;
import com.yanqu.road.server.manger.player.GamePlayerMgr;
import com.yanqu.road.server.manger.union.CrossUnionMgr;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.YanQuMessageUtils;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;
import com.yanqu.road.utils.string.StringUtils;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class BeautyEscortModule extends GeneralModule {

    /**
     * 美女数据
     */
    private Map<Integer, EscortBeautyData> beautyDataMap = new ConcurrentHashMap<>();

    public BeautyEscortModule(GamePlayer player) {
        super(player);
    }

    @Override
    public boolean loadData() {
        Map<Integer, EscortBeautyData> tempBeautyDataMap = BeautyEscortBussiness.getEscortBeautyDataMap(player.getUserId());
        beautyDataMap = tempBeautyDataMap;

        try {
            for (Integer beautyId : beautyDataMap.keySet()) {
                UserBeauty userBeauty = player.getModule(BeautyModule.class).getUserBeauty(beautyId);
                if (userBeauty == null) {
                    beautyDataMap.remove(beautyId);
                }
            }
        } catch (Exception e) {
            log.error(e);
        }

        return true;
    }

    @Override
    public boolean afterLoadData() {
        return true;
    }

    @Override
    public boolean saveData() {

        for (Map.Entry<Integer, EscortBeautyData> beautyDataEntry : beautyDataMap.entrySet()) {
            EscortBeautyData beautyData = beautyDataEntry.getValue();
            if(beautyData.isInsertOption()){
                BeautyEscortBussiness.addEscortBeautyData(beautyData);
            }else if(beautyData.isUpdateOption()){
                BeautyEscortBussiness.updateEscortBeautyData(beautyData);
            }
        }

        return true;
    }

    @Override
    public void afterLogin() {
        syncUserData();
        initUserData();
        loginReqRedDot();
    }

    /**
     * 红点请求
     */
    private void loginReqRedDot() {
        if(systemOpen()){
            BeautyEscortProto.CrossBeautyEscortRedDotReqMsg.Builder reqMsg = BeautyEscortProto.CrossBeautyEscortRedDotReqMsg.newBuilder();
            Map<Long, CrossUnionMember> unionMemberMap = CrossUnionMgr.getUnionMemberMap(player.getUserInfo().getUnionUid());
            if(unionMemberMap != null){
                for (Map.Entry<Long, CrossUnionMember> memberEntry : unionMemberMap.entrySet()) {
                    reqMsg.addMember(memberEntry.getKey());
                }
            }
            reqMsg.setUnionUid("");
            EscortWeekUserValue userValue = BeautyEscortMgr.getEscortWeekUserValue(BeautyEscortMgr.getPreWeekId(), player.getUserId());
            if(userValue != null){
                reqMsg.setUnionUid(userValue.getUnionUid());
            }
            player.sendPacket(Protocol.C_BEAUTY_ESCORT_RED_DOT_SYNC, reqMsg);
        }
    }

    /**
     * 初始数据（分组开放时）
     */
    public void initUserData(){
       int weekId = BeautyEscortMgr.getThisWeekId();
       BeautyEscortMgr.initUserData(weekId, player.getUserId(), player.getUserInfo().getUnionUid());
    }

    /**
     * 分组状态同步
     */
    private void syncUserData() {
        BeautyEscortProto.BeautyEscortUserDataSyncMsg.Builder syncMsg = BeautyEscortProto.BeautyEscortUserDataSyncMsg.newBuilder();
        syncMsg.setCrossOpen(false);
        player.sendPacket(Protocol.C_BEAUTY_ESCORT_USER_DATA_SYNC, syncMsg);
    }

    /**
     * 系统是否对玩家开放
     */
    public boolean systemOpen(){
        if(StringUtils.isNullOrEmpty(player.getUserInfo().getUnionUid())){
            return false;
        }
        //商会等级限制
        UnionInfo unionInfo = CrossUnionMgr.getUnionInfo(player.getUserInfo().getUnionUid());
        if(unionInfo == null){
            return false;
        }
        if(UnionConfigMgr.getUnionLv(unionInfo.getExperience()) < GameConfig.ESCORT_OPEN_UNION_LEVEL) {
            return false;
        }
        //系统开关
        if(!SystemOpenMgr.systemOpen(player, eSystemId.BeautyEscort.getValue())){
            return false;
        }
        return true;
    }

    /**
     * 初始美女数据
     */
    public EscortBeautyData getByBeautyId(int beautyId){
        if(!beautyDataMap.containsKey(beautyId)){
            synchronized (beautyDataMap) {
                if(!beautyDataMap.containsKey(beautyId)) {
                    EscortBeautyData beautyData = new EscortBeautyData();
                    beautyData.setBeautyId(beautyId);
                    beautyData.setUserId(player.getUserId());
                    beautyData.setInsertOption();
                    beautyData.setResetTime(DateHelper.getTodayZeroTimeStamp());
                    beautyDataMap.put(beautyId, beautyData);
                }
            }
        }
        return beautyDataMap.get(beautyId);
    }

    public void initSystem() {initUserData();}

    /**
     * 接镖+派遣美女(十连)
     */
    public int acceptAndDispatchBeautyTen(int type, int client, List<Integer> beautyList, boolean autoAccelerate) {
        boolean open = player.getModule(BeautyEscortModule.class).systemOpen();
        if(!open){
            return GameErrorCode.E_BEAUTY_ESCORT_SYSTEM_NO_OPEN;
        }

        EscortDartTypeInfo typeInfo = ConfigMgr.getDartTypeInfoMap().get(type);
        if(BeautyEscortMgr.isFree(typeInfo)){
            //免费镖车 不能十连
            return GameErrorCode.E_REQUEST_ARGUMENT_ERROR;
        }

        Set<Integer> beautyIdSet = new HashSet<>(beautyList);

        if(beautyIdSet.size() != 5){
            return GameErrorCode.E_BEAUTY_ESCORT_DISPATCH_NUM_ERROR;
        }

        //检查美女参数是否有效
        BeautyModule beautyModule = player.getModule(BeautyModule.class);
        List<EscortBeautyDispatch> beautyDispatchList = new ArrayList<>();
        for (int beautyId : beautyIdSet) {
            UserBeauty userBeauty = beautyModule.getUserBeauty(beautyId);
            if(userBeauty == null){
                return GameErrorCode.E_BEAUTY_NO_FOUND;
            }
            EscortBeautyDispatch dispatch = new EscortBeautyDispatch();
            dispatch.setBeautyId(beautyId);
            dispatch.setGlamour(userBeauty.getTotalGlamour());
            beautyDispatchList.add(dispatch);
        }

        Property consume  = PropertyHelper.parseStringToProperty(typeInfo.getConsume());
        consume.rideProperty(10);
        if(!player.getModule(CurrencyModule.class).currencyIsEnough(consume)){
            return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
        }

        //加速道具是否足够
        GoodsInfo goodsInfo = GoodsMgr.getGoodsById(eItemId.BEAUTY_ESCORT_JI_XING_LING.getValue());
        if(goodsInfo == null){
            return GameErrorCode.E_GOODS_NO_EXIST;
        }
        int param1 = goodsInfo.getParamList().get(0).intValue();        //单道具减分钟数
        int needTimes = typeInfo.getTakeTime() * 10;
        int needCount = needTimes / param1;
        if(needTimes % param1 != 0){
            needCount++;
        }
        Property itemConsume = PropertyHelper.parseStringToProperty(eItemId.BEAUTY_ESCORT_JI_XING_LING.getValue() + "=" + needCount);
        if(!player.getModule(CurrencyModule.class).currencyIsEnough(itemConsume)){
            return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
        }

        //预扣
        Property allConsume = new Property();
        allConsume.addProperty(itemConsume);
        allConsume.addProperty(consume);
        player.getModule(PreReduceModule.class).preReduce(allConsume);


        BeautyEscortProto.CrossBeautyEscortAcceptDispatchTenReqMsg.Builder crossReq = BeautyEscortProto.CrossBeautyEscortAcceptDispatchTenReqMsg.newBuilder();
        crossReq.setTypeId(type);
        crossReq.setClient(client);
        crossReq.addAllBeauty(BeautyEscortMgr.parseBeautyDispatchBuilderList(beautyDispatchList));
        crossReq.setAllConsume(PropertyHelper.parsePropertyToString(allConsume));
        YanQuMessage crossMsg = YanQuMessageUtils.buildMessage(Protocol.C_BEAUTY_ESCORT_DART_ACCEPT_DISPATCH_BEAUTY_TEN, crossReq);
        GamePlayerMgr.sendPacket(player.getUserId(), crossMsg);

        return 0;
    }

    /**
     * 接镖+派遣美女
     */
    public int acceptAndDispatchBeauty(int type, int client, List<Integer> beautyList, boolean autoAccelerate) {
        boolean open = player.getModule(BeautyEscortModule.class).systemOpen();
        if(!open){
            return GameErrorCode.E_BEAUTY_ESCORT_SYSTEM_NO_OPEN;
        }
        Set<Integer> beautyIdSet = new HashSet<>();
        for(int beautyId : beautyList){
            beautyIdSet.add(beautyId);
        }
        if(beautyIdSet.size() != 5){
            return GameErrorCode.E_BEAUTY_ESCORT_DISPATCH_NUM_ERROR;
        }
        EscortDartTypeInfo typeInfo = ConfigMgr.getDartTypeInfoMap().get(type);
        List<EscortBeautyDispatch> beautyDispatchList = new ArrayList<>();
        //检查美女参数是否有效
        BeautyModule beautyModule = player.getModule(BeautyModule.class);
        for (int beautyId : beautyIdSet) {
            UserBeauty userBeauty = beautyModule.getUserBeauty(beautyId);
            if(userBeauty == null){
                return GameErrorCode.E_BEAUTY_NO_FOUND;
            }else {
                EscortBeautyDispatch dispatch = new EscortBeautyDispatch();
                dispatch.setBeautyId(beautyId);
                dispatch.setGlamour(userBeauty.getTotalGlamour());
                beautyDispatchList.add(dispatch);
            }
        }
        List<Integer> buyBeautyList = new ArrayList<>();
        Property buyConsume = new Property();
        synchronized (beautyDataMap) {
            //是否足够走镖消耗
            if(!BeautyEscortMgr.isFree(typeInfo)){
                Property consume  = PropertyHelper.parseStringToProperty(typeInfo.getConsume());
                if(!player.getModule(CurrencyModule.class).currencyIsEnough(consume)){
                    return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
                }
            }else {
                //免费的才需要扣次数
                //美女次数是否需要购买
                for (int beautyId : beautyList) {
                    EscortBeautyData beautyData = player.getModule(BeautyEscortModule.class).getByBeautyId(beautyId);
                    if (beautyData.getEscortTimes() >= getEscortFreeTimes()) {
                        buyBeautyList.add(beautyId);
                    }
                }
            }

            //是否足够购买消耗
            if (buyBeautyList.size() > 0) {
                for (int beautyId : buyBeautyList) {
                    EscortBeautyData beautyData = getByBeautyId(beautyId);
                    //需要购买
                    if (beautyData.getEscortTimes() >= GameConfig.ESCORT_TIMES_PER_WEEK) {
                        int ingotsNum = ConfigMgr.getEscortRecoverConsume(1 + beautyData.getBuyEscortTimes());
                        buyConsume.addProperty(GameConfig.GAME_MONEY_INGOTS, BigInteger.valueOf(ingotsNum));
                    }
                }
                if (!player.getModule(CurrencyModule.class).currencyIsEnough(buyConsume)) {
                    return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
                }

                //预扣
                player.getModule(PreReduceModule.class).preReduce(PropertyHelper.parsePropertyToString(buyConsume));
                for(int beautyId : buyBeautyList){
                    EscortBeautyData beautyData = getByBeautyId(beautyId);
                    beautyData.setBuyEscortTimes(1 + beautyData.getBuyEscortTimes());
                }
            }

            //走镖消耗预扣
            if(!BeautyEscortMgr.isFree(typeInfo)) {
                player.getModule(PreReduceModule.class).preReduce(typeInfo.getConsume());
            }else {
                //免费的才扣次数
                //美女押镖次数
                for (int beautyId : beautyList) {
                    if(!buyBeautyList.contains(beautyId)){
                        EscortBeautyData beautyData = player.getModule(BeautyEscortModule.class).getByBeautyId(beautyId);
                        beautyData.setEscortTimes(1 + beautyData.getEscortTimes());
                    }
                }
            }

        }

        //计算加速
        int needCount = 0;
        int accelerateTime = 0;         //单位min
        if(autoAccelerate) {
            int takeTime = typeInfo.getTakeTime();          //押镖持续分钟数
//            log.info("acceptAndDispatchBeauty userId:{},takeTime:{}", player.getUserId(), takeTime);
            GoodsInfo goodsInfo = GoodsMgr.getGoodsById(eItemId.BEAUTY_ESCORT_JI_XING_LING.getValue());
            int param1 = 0;
            if(null != goodsInfo){
                param1 = goodsInfo.getParamList().get(0).intValue();        //单道具减分钟数
//                log.info("acceptAndDispatchBeauty userId:{},param1:{}", player.getUserId(), param1);
                if(takeTime % param1 == 0) {
                    needCount = takeTime / param1;
//                    log.info("acceptAndDispatchBeauty userId:{},mod:{},needCount:{}", player.getUserId(), 0, needCount);
                }else {
                    needCount = takeTime / param1 + 1;
//                    log.info("acceptAndDispatchBeauty userId:{},mod:{},needCount:{}", player.getUserId(), takeTime % param1, needCount);
                }
            }
            CurrencyModule currencyModule = player.getModule(CurrencyModule.class);
            BagModule bagModule = player.getModule(BagModule.class);
            long bagCount = bagModule.getUserBagItemCount(eItemId.BEAUTY_ESCORT_JI_XING_LING.getValue());
            if(needCount > bagCount){
                needCount = (int) bagCount;
            }
            Property accelerateConsume = new Property(eItemId.BEAUTY_ESCORT_JI_XING_LING.getValue(), needCount);
            if(needCount > 0) {
                while (!currencyModule.currencyIsEnough(accelerateConsume)) {
                    needCount--;
                    accelerateConsume = new Property(eItemId.BEAUTY_ESCORT_JI_XING_LING.getValue(), needCount);
                    if (needCount <= 0) {
                        break;
                    }
                }
            }
            if(needCount > 0) {
                accelerateTime = param1 * needCount;
//                log.info("acceptAndDispatchBeauty userId:{},needCount:{},accelerateTime{}", player.getUserId(), needCount, accelerateTime);
                player.getModule(PreReduceModule.class).preReduce(accelerateConsume);
            }
        }

        BeautyEscortProto.CrossBeautyEscortAcceptDispatchReqMsg.Builder reqMsg = BeautyEscortProto.CrossBeautyEscortAcceptDispatchReqMsg.newBuilder();
        reqMsg.setTypeId(type);
        reqMsg.setClient(client);
        reqMsg.addAllBeauty(BeautyEscortMgr.parseBeautyDispatchBuilderList(beautyDispatchList));
        reqMsg.addAllBuyBeauty(buyBeautyList);
        reqMsg.setBuyBeautyConsume(PropertyHelper.parsePropertyToString(buyConsume));
        reqMsg.setAutoAccelerate(autoAccelerate);
        reqMsg.setNeedAccelerateCount(needCount);
        reqMsg.setAccelerateTime(accelerateTime);
        YanQuMessage crossMsg = YanQuMessageUtils.buildMessage(Protocol.C_BEAUTY_ESCORT_DART_ACCEPT_DISPATCH_BEAUTY, reqMsg);
        GamePlayerMgr.sendPacket(player.getUserId(), crossMsg);
        return 0;
    }

    public int getEscortFreeTimes() {
        int addFreeTimes = 0;
        List<UserPatrons> userPatronsList = player.getModule(PatronsModule.class).getUserPatronsList();
        for (UserPatrons patrons : userPatronsList) {
            for (UserPatronsSkill skill : patrons.getSkillList()) {
                SkillInfo skillInfo = SkillMgr.getSkillInfo(skill.getSkillId());
                if(skillInfo == null){
                    continue;
                }
                if (skillInfo.getType() == eSkillType.BeautyEscortFreeTimesAddition.getValue()) {
                    addFreeTimes += SkillMgr.getSkillAddition(skillInfo, skill.getSkillLv());
                }
            }
        }
        return addFreeTimes + GameConfig.ESCORT_TIMES_PER_WEEK;
    }

    /**
     * 同步美女数据
     */
    public int syncBeautyData() {
        BeautyEscortProto.BeautyEscortBeautyDataRespMsg.Builder respMsg = BeautyEscortProto.BeautyEscortBeautyDataRespMsg.newBuilder();
        for (Map.Entry<Integer, EscortBeautyData> beautyDataEntry : beautyDataMap.entrySet()) {
            EscortBeautyData beautyData = beautyDataEntry.getValue();
            BeautyEscortProto.BeautyEscortBeautyDataTemp.Builder builder = BeautyEscortProto.BeautyEscortBeautyDataTemp.newBuilder();
            builder.setBeautyId(beautyData.getBeautyId());
            builder.setEscortTimes(beautyData.getEscortTimes());
            builder.setRobDartTimes(beautyData.getRobDartTimes());
            builder.setBuyEscortTimes(beautyData.getBuyEscortTimes());
            builder.setBuyRobDartTimes(beautyData.getBuyRobDartTimes());
            respMsg.addBeauty(builder);
        }
        respMsg.setRet(0);
        player.sendPacket(Protocol.U_BEAUTY_ESCORT_BEAUTY_DATA, respMsg);
        return 0;
    }

    /**
     * 返还美女走镖次数
     */
    public void restoreBeautyData(List<Integer> buyList, List<EscortBeautyDispatch> beautyDispatchList) {
        synchronized (beautyDataMap) {
            for (EscortBeautyDispatch dispatch : beautyDispatchList) {
                EscortBeautyData beautyData = getByBeautyId(dispatch.getBeautyId());
                if (buyList.contains(dispatch.getBeautyId())) {
                    beautyData.setBuyEscortTimes(beautyData.getBuyEscortTimes() - 1);
                }else {
                    beautyData.setEscortTimes(beautyData.getEscortTimes() - 1);
                }
            }
        }
    }

    /**
     * 劫镖
     */
    public int rob(long serverId, long userId, long dartId, List<Integer> beautyList, int position) {
        boolean open = player.getModule(BeautyEscortModule.class).systemOpen();
        if(!open){
            return GameErrorCode.E_BEAUTY_ESCORT_SYSTEM_NO_OPEN;
        }
        Set<Integer> beautyIdSet = new HashSet<>();
        for(int beautyId : beautyList){
            beautyIdSet.add(beautyId);
        }
        if(beautyIdSet.size() != 5){
            return GameErrorCode.E_BEAUTY_ESCORT_DISPATCH_NUM_ERROR;
        }
        List<BeautyEscortProto.BeautyEscortBeautyDispatchDataTemp> dispatchDataList = new ArrayList<>();
        Map<Integer, UserBeauty> beautyMap =  player.getModule(BeautyModule.class).getBeautyMap();
        Iterator<Integer> iterator = beautyList.iterator();
        while(iterator.hasNext()){
            int beautyId = iterator.next();
            if(beautyMap.containsKey(beautyId)){
                UserBeauty userBeauty = beautyMap.get(beautyId);
                dispatchDataList.add(BeautyEscortMgr.getBeautyDispatchBuilder(beautyId, userBeauty.getTotalGlamour()).build());
            }else {
                iterator.remove();
            }
        }
        if(beautyList.size() != 5){
            return GameErrorCode.E_BEAUTY_ESCORT_DISPATCH_NUM_ERROR;
        }
        List<Integer> buyBeautyList = new ArrayList<>();
        //美女次数需要扣除的元宝
        Property consume = new Property();
        synchronized (beautyDataMap) {
            for (int beautyId : beautyList) {
                EscortBeautyData beautyData = getByBeautyId(beautyId);
                //需要购买
                if (beautyData.getRobDartTimes() >= GameConfig.ESCORT_BEAUTY_FIGHT_INITIAL_TIMES) {
                    int ingotsNum = ConfigMgr.getFightRecoverConsume(1 + beautyData.getBuyRobDartTimes());
                    consume.addProperty(GameConfig.GAME_MONEY_INGOTS, BigInteger.valueOf(ingotsNum));
                    buyBeautyList.add(beautyId);
                }
            }
            if (!consume.isNothing()) {
                if (!player.getModule(CurrencyModule.class).currencyIsEnough(consume)) {
                    return GameErrorCode.E_BAG_INGOTS_NO_ENOUGH;
                }
                //预扣除
                player.getModule(PreReduceModule.class).preReduce(PropertyHelper.parsePropertyToString(consume));
            }

            //扣除美女次数
            for (int beautyId : beautyList) {
                EscortBeautyData beautyData = getByBeautyId(beautyId);
                if (buyBeautyList.contains(beautyId)) {
                    beautyData.setBuyRobDartTimes(1 + beautyData.getBuyRobDartTimes());
                } else {
                    beautyData.setRobDartTimes(1 + beautyData.getRobDartTimes());
                }
            }
        }

        BeautyEscortProto.CrossBeautyEscortRobCartReqMsg.Builder reqMsg = BeautyEscortProto.CrossBeautyEscortRobCartReqMsg.newBuilder();
        reqMsg.setDartId(dartId);
        reqMsg.setUserId(userId);
        reqMsg.setServerId(serverId);
        reqMsg.addAllBeauty(dispatchDataList);
        reqMsg.addAllBuyBeauty(buyBeautyList);
        reqMsg.setPosition(position);
        reqMsg.setBuyConsume(PropertyHelper.parsePropertyToString(consume));
        player.sendPacket(Protocol.C_BEAUTY_ESCORT_ROB_CART, reqMsg);
        return 0;
    }

    public Map<Integer, EscortBeautyData> getBeautyDataMap() {
        return beautyDataMap;
    }

    /**
     * 事件奖励
     */
    public void addEventReward(String reward, long exp, List<EscortBeautyDispatch> dispatchList, long dartId, EscortBeautyEvent beautyEvent) {
        int weekId = BeautyEscortMgr.getThisWeekId();
        long allExp = addBeautyEscortExp(reward, exp, dispatchList, weekId);
        Property goodsReward = PropertyHelper.parseStringToProperty(reward);
        //去掉美女走镖经验道具奖励，因为已记录到美女身上
        goodsReward.removeProperty(eItemId.BEAUTY_ESCORT_EXP_GOODS.getValue());

        player.getModule(CurrencyModule.class).addCurrency(goodsReward, eLogMoneyType.BeautyEscort, eLogMoneyType.BeautyEscortEventReward);

        //美女押镖经验榜单
        player.notifyListener(eGamePlayerEventType.BeautyEscortAddExpRank.getValue(), allExp);
        player.notifyListener(eGamePlayerEventType.BeautyEscortExpAdd.getValue(), allExp);
        player.notifyListener(eGamePlayerEventType.ServerBeautyEscortAddExpRank.getValue(), allExp);
        player.notifyListener(eGamePlayerEventType.OnlyEscortAddExpRank.getValue(), allExp);
        player.notifyListener(eGamePlayerEventType.ServerOnlyEscortAddExpRank.getValue(), allExp);
        //冲榜
        BeautyEscortMgr.changeUnionRank(player.getUserInfo().getUnionUid(), player.getUserId(), UnionRiseRankArgs.NOTIFY_TYPE_NORMAL, weekId);
        syncUserBeauty(dispatchList);

        AutoLogMgr.add(new LogBeautyEscortEventReward(player.getUserId(), dartId, beautyEvent.getUnionUid(), beautyEvent.getUnionLv(),
                beautyEvent.getEventTime(), beautyEvent.getEventId(), reward, beautyEvent.getDamage()));
    }

    private void syncUserBeauty(List<EscortBeautyDispatch> dispatchList) {
        //同步美女
        BeautyModule beautyModule = player.getModule(BeautyModule.class);
        List<UserBeauty>  userBeautyList = new ArrayList<>();
        for (EscortBeautyDispatch dispatch : dispatchList) {
            userBeautyList.add(beautyModule.getUserBeauty(dispatch.getBeautyId()));
        }
        beautyModule.syncUserBeauty(userBeautyList, false);
    }

    /**
     * 走镖奖励
     */
    public void addDartReward(String reward, long exp, List<EscortBeautyDispatch> dispatchList, long dartId) {
        int weekId = BeautyEscortMgr.getThisWeekId();
        long allExp = addBeautyEscortExp(reward, exp, dispatchList, weekId);
        Property goodsReward = PropertyHelper.parseStringToProperty(reward);
        //去掉美女走镖经验道具奖励，因为已记录到美女身上
        goodsReward.removeProperty(eItemId.BEAUTY_ESCORT_EXP_GOODS.getValue());

        player.getModule(CurrencyModule.class).addCurrency(goodsReward, eLogMoneyType.BeautyEscort, eLogMoneyType.BeautyEscortReward);

        //美女押镖经验榜单
        player.notifyListener(eGamePlayerEventType.BeautyEscortAddExpRank.getValue(), allExp);
        player.notifyListener(eGamePlayerEventType.BeautyEscortExpAdd.getValue(), allExp);
        player.notifyListener(eGamePlayerEventType.ServerBeautyEscortAddExpRank.getValue(), allExp);
        player.notifyListener(eGamePlayerEventType.OnlyEscortAddExpRank.getValue(), allExp);
        player.notifyListener(eGamePlayerEventType.ServerOnlyEscortAddExpRank.getValue(), allExp);
        //冲榜
        BeautyEscortMgr.changeUnionRank(player.getUserInfo().getUnionUid(), player.getUserId(), UnionRiseRankArgs.NOTIFY_TYPE_NORMAL, weekId);
        syncUserBeauty(dispatchList);

        //走镖奖励日志
        AutoLogMgr.add(new LogBeautyEscortDartReward(player.getUserId(), dartId, player.getUserInfo().getUnionUid(), reward, allExp));
    }

    /**
     * 加美女经验
     */
    private long addBeautyEscortExp(String reward, long exp, List<EscortBeautyDispatch> dispatchList, int weekId) {
        //log.debug("{}, addBeautyEscortExp reward {}", player.getUserId(), reward);
        //经验
        Property property = PropertyHelper.parseStringToProperty(reward);
        long base = exp;
        if(exp == 0){
            base = property.getCountByGoodsId(eItemId.BEAUTY_ESCORT_EXP_GOODS.getValue()).longValue();
        }
        List<LogBeautySkillExp> logList = new ArrayList<>();
        long allExp = 0;
        if(base > 0) {
            List<UserBeauty> beautyList = new ArrayList<>();
            for (EscortBeautyDispatch dispatch : dispatchList) {
                UserBeauty userBeauty = player.getModule(BeautyModule.class).getUserBeauty(dispatch.getBeautyId());
                BeautyInfo beautyInfo = BeautyMgr.getBeautyInfo(dispatch.getBeautyId());
                if (userBeauty != null && beautyInfo != null) {
                    synchronized (userBeauty) {
                        long addition = CurioMgr.getSkillAdditionBySkillType(eSkillType.SpecialOccupationBeautyEscortSkill.getValue(), player, beautyInfo.getOccupation());
                        int expAdd = BigDecimal.valueOf(base).multiply(BigDecimal.valueOf(1000 + addition)).divide(BigDecimal.valueOf(1000), 0, BigDecimal.ROUND_UP).intValue();
                        player.getModule(BeautyModule.class).addBeautyEscortExp(userBeauty, expAdd);
                        logList.add(new LogBeautySkillExp(player.getUserId(), userBeauty.getBeautyId(), expAdd, userBeauty.getEscortExp(), eLogMoneyType.BeautyEscort.getValue(), eLogMoneyType.BeautyEscortReward.getValue()));
                        allExp += expAdd;
                    }
                    beautyList.add(userBeauty);
                }
            }
            player.getModule(BeautyModule.class).syncUserBeauty(beautyList, false);

            //log.debug("{}, addBeautyEscortExp {}", player.getUserId(), exp);
            //long allExp = exp * dispatchList.size();
            //经验冲榜
            EscortWeekUserValue userValue = BeautyEscortMgr.getEscortWeekUserValueOrInit(weekId, player.getUserId());
            synchronized (userValue) {
                userValue.setValue(userValue.getValue() + allExp);
                userValue.setModifyTime(System.currentTimeMillis());
            }
            //经验获得日志
            for (LogBeautySkillExp skillExp : logList) {
                AutoLogMgr.add(skillExp);
            }
            return allExp;
        }
        return 0;
    }

    /**
     * 领取商会排行奖励（上周）
     */
    public int getUnionRankReward() {
        int preWeekId = BeautyEscortMgr.getPreWeekId();
        //5分钟后才可领奖
        Calendar cal = Calendar.getInstance();
        if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
            long zeroTime = DateHelper.getTodayZeroTimeStamp();
            if(cal.getTimeInMillis() < (zeroTime + (ConfigMgr.getEscortingEndMinute() + 5) * 60 * 1000)){
                return GameErrorCode.E_BEAUTY_ESCORT_IN_REWARD_SETTLEMENT_TIME;
            }
        }
        EscortWeekUserValue userValue = BeautyEscortMgr.getEscortWeekUserValue(preWeekId, player.getUserId());
        if(userValue == null){
            return GameErrorCode.E_BEAUTY_ESCORT_SYSTEM_NO_OPEN;
        }
        if(userValue.isGetReward()){
            return GameErrorCode.E_BEAUTY_ESCORT_HAD_GET_REWARD;
        }
        if(StringUtils.isNullOrEmpty(userValue.getUnionUid())){
            return GameErrorCode.E_UNION_NO_JOIN_UNION;
        }
        BeautyEscortProto.CrossBeautyEscortGetUnionRankRewardReqMsg.Builder reqMsg = BeautyEscortProto.CrossBeautyEscortGetUnionRankRewardReqMsg.newBuilder();
        reqMsg.setWeekId(preWeekId);
        reqMsg.setUnionUid(userValue.getUnionUid());
        player.sendPacket(Protocol.C_BEAUTY_ESCORT_GET_UNION_RANK_REWARD, reqMsg);
        return 0;
    }

    /**
     * 领取商会排行奖励-从跨服（上周）
     */
    public RewardResult getUnionRankRewardFromCross(int groupId, int weekId, int rank) {
        RewardResult rewardResult = new RewardResult(0);

        int preWeekId = BeautyEscortMgr.getPreWeekId();
        if(weekId != preWeekId){
            rewardResult.setRet(GameErrorCode.E_BEAUTY_ESCORT_OVER_RECEIVE_TIME);
            return rewardResult;
        }
        EscortWeekUserValue userValue = BeautyEscortMgr.getEscortWeekUserValue(weekId, player.getUserId());
        if(userValue == null){
            rewardResult.setRet(GameErrorCode.E_BEAUTY_ESCORT_SYSTEM_NO_OPEN);
            return rewardResult;
        }
        if(StringUtils.isNullOrEmpty(userValue.getUnionUid())){
            rewardResult.setRet(GameErrorCode.E_UNION_NO_JOIN_UNION);
            return rewardResult;
        }
        synchronized (userValue){
            EscortWeekRewardInfo rewardInfo;
            if(userValue.isGetReward()){
                rewardResult.setRet(GameErrorCode.E_BEAUTY_ESCORT_HAD_GET_REWARD);
                return rewardResult;
            }
            //跨服分组
            if(groupId < GameServer.getInstance().getServerId()){
                if(userValue.getPosition() == eUnionPosition.Master.getValue()){
                    rewardInfo = ConfigMgr.getCrossRankChairReward(rank);
                }else {
                    rewardInfo = ConfigMgr.getCrossRankReward(rank);
                }
            }else {
                //区服范围
                if(userValue.getPosition() == eUnionPosition.Master.getValue()){
                    rewardInfo = ConfigMgr.getRankChairReward(rank);
                }else {
                    rewardInfo = ConfigMgr.getRankReward(rank);
                }
            }
            if(rewardInfo == null){
                rewardResult.setRet(GameErrorCode.E_BEAUTY_ESCORT_NO_RANK_REWARD);
                return rewardResult;
            }
            Property property = PropertyHelper.parseStringToProperty(rewardInfo.getRewards());
            if(rewardInfo.getVal() > 0 && userValue.getValue() >= rewardInfo.getVal()){
                property.addProperty(PropertyHelper.parseStringToProperty(rewardInfo.getAddRewards()));
            }
            rewardResult.setReward(PropertyHelper.parsePropertyToString(property));
            userValue.setReward(rewardResult.getReward());
            userValue.setGetReward(true);
            userValue.setGetRewardTime(System.currentTimeMillis());
            player.getModule(CurrencyModule.class).addCurrency(rewardResult.getReward(), eLogMoneyType.BeautyEscort, eLogMoneyType.BeautyEscortRankReward);
        }

        return rewardResult;
    }

    /**
     * 返还劫镖次数
     */
    public void restoreRobTimes(List<EscortBeautyDispatch> dispatchList, List<Integer> buyBeautyList) {
        synchronized (beautyDataMap) {
            //返还劫镖次数
            for (EscortBeautyDispatch dispatch : dispatchList) {
                EscortBeautyData beautyData = getByBeautyId(dispatch.getBeautyId());
                if (buyBeautyList.contains(dispatch.getBeautyId())) {
                    beautyData.setBuyRobDartTimes(beautyData.getBuyRobDartTimes() - 1);
                }else {
                    beautyData.setRobDartTimes(beautyData.getRobDartTimes() - 1);
                }
            }
        }
    }

    /**
     * 加速镖车
     */
    public void reduceEscortTime(int time, int num, int cartId) {
        BeautyEscortProto.CrossBeautyEscortReduceDartTimeReqMsg.Builder reqMsg = BeautyEscortProto.CrossBeautyEscortReduceDartTimeReqMsg.newBuilder();
        reqMsg.setCartId(cartId);
        reqMsg.setTime(time);
        reqMsg.setGoodsNum(num);
        player.sendPacket(Protocol.C_BEAUTY_ESCORT_DART_TIME_REDUCE, reqMsg);
    }

    //每周重置
    public void resetOneDay(){
        try {
            boolean reset = false;
            Date monday = DateHelper.getThisWeekMonday(new Date());
            long time = monday.getTime();
            for (Map.Entry<Integer, EscortBeautyData> beautyDataEntry : beautyDataMap.entrySet()) {
                EscortBeautyData beautyData = beautyDataEntry.getValue();
                if (time > beautyData.getResetTime()) {
                    beautyData.setResetTime(time);
                    beautyData.setEscortTimes(0);
                    beautyData.setRobDartTimes(0);
                    beautyData.setBuyEscortTimes(0);
                    beautyData.setBuyRobDartTimes(0);
                    reset = true;
                }
            }
            if (reset) {
                //红点请求
                if(!StringUtils.isNullOrEmpty(player.getUserInfo().getUnionUid())){
                    //商会等级限制
                    UnionInfo unionInfo = CrossUnionMgr.getUnionInfo(player.getUserInfo().getUnionUid());
                    if(UnionConfigMgr.getUnionLv(unionInfo.getExperience()) >= GameConfig.ESCORT_OPEN_UNION_LEVEL) {
                        BeautyEscortProto.CrossBeautyEscortRedDotReqMsg.Builder reqMsg = BeautyEscortProto.CrossBeautyEscortRedDotReqMsg.newBuilder();
                        player.sendPacket(Protocol.C_BEAUTY_ESCORT_RED_DOT_SYNC, reqMsg);
                    }
                }
            }
        }catch (Exception e){
            log.error(e.getMessage(), e);
        }
    }

    /**
     * 反击
     */
    public int beatBack(long userId, long dartId, long enemyUserId, long enemyDartId, List<Integer> beautyList, long serverId) {
        Set<Integer> beautyIdSet = new HashSet<>();
        for(int beautyId : beautyList){
            beautyIdSet.add(beautyId);
        }
        if(beautyIdSet.size() != 5){
            return GameErrorCode.E_BEAUTY_ESCORT_DISPATCH_NUM_ERROR;
        }
        List<BeautyEscortProto.BeautyEscortBeautyDispatchDataTemp> dispatchDataList = new ArrayList<>();
        Map<Integer, UserBeauty> beautyMap =  player.getModule(BeautyModule.class).getBeautyMap();
        Iterator<Integer> iterator = beautyList.iterator();
        while(iterator.hasNext()){
            int beautyId = iterator.next();
            if(beautyMap.containsKey(beautyId)){
                UserBeauty userBeauty = beautyMap.get(beautyId);
                dispatchDataList.add(BeautyEscortMgr.getBeautyDispatchBuilder(beautyId, userBeauty.getTotalGlamour()).build());
            }else {
                iterator.remove();
            }
        }
        if(beautyList.size() != 5){
            return GameErrorCode.E_BEAUTY_ESCORT_DISPATCH_NUM_ERROR;
        }
        List<Integer> buyBeautyList = new ArrayList<>();

        //美女次数需要扣除的元宝
        Property consume = new Property();
        synchronized (beautyDataMap) {
            for (int beautyId : beautyList) {
                EscortBeautyData beautyData = getByBeautyId(beautyId);
                //需要购买
                if (beautyData.getRobDartTimes() >= GameConfig.ESCORT_BEAUTY_FIGHT_INITIAL_TIMES) {
                    int ingotsNum = ConfigMgr.getFightRecoverConsume(1 + beautyData.getBuyRobDartTimes());
                    consume.addProperty(GameConfig.GAME_MONEY_INGOTS, BigInteger.valueOf(ingotsNum));
                    buyBeautyList.add(beautyId);
                }
            }
            if (!consume.isNothing()) {
                if (!player.getModule(CurrencyModule.class).currencyIsEnough(consume)) {
                    return GameErrorCode.E_BAG_INGOTS_NO_ENOUGH;
                }
                //预扣除
                player.getModule(PreReduceModule.class).preReduce(PropertyHelper.parsePropertyToString(consume));
            }

            //扣除美女次数
            for (int beautyId : beautyList) {
                EscortBeautyData beautyData = getByBeautyId(beautyId);
                if (buyBeautyList.contains(beautyId)) {
                    beautyData.setBuyRobDartTimes(1 + beautyData.getBuyRobDartTimes());
                } else {
                    beautyData.setRobDartTimes(1 + beautyData.getRobDartTimes());
                }
            }
        }

        BeautyEscortProto.CrossBeautyEscortBeatBackReqMsg.Builder reqMsg = BeautyEscortProto.CrossBeautyEscortBeatBackReqMsg.newBuilder();
        reqMsg.setDartId(dartId);
        reqMsg.setUserId(userId);
        reqMsg.setEnemyUserId(enemyUserId);
        reqMsg.setEnemyDartId(enemyDartId);
        reqMsg.setEnemyServerId(serverId);
        reqMsg.addAllBeauty(dispatchDataList);
        reqMsg.addAllBuyBeauty(buyBeautyList);
        reqMsg.setBuyConsume(PropertyHelper.parsePropertyToString(consume));
        player.sendPacket(Protocol.C_BEAUTY_ESCORT_BEAT_BACK, reqMsg);
        return 0;
    }
}
